package neuralmusic.brain.module;

import java.awt.Rectangle;
import java.util.List;
import java.util.Random;
import java.util.Vector;


import uk.co.drpj.util.tweaks.Tweakable;
import uk.co.drpj.util.tweaks.TweakableDouble;


/**
 *  A GrayModule is a 2D set of neurons.
 *  
 *  
 * 
 * @author pjl
 *
 */

public class GrayModule extends BasicModule {
	
	TweakableDouble threshModGrey;
	
	public GrayModule(int nNeurons, int nConnect, Rectangle rect,
			float minWeight,float maxWeight, NeuronParams pramGrey,
		 Brain brain,float delayMin,float delayMax,Vector<Tweakable> tweaks,double distFract){
		
		/***
		 * 
		 * Construct the neurons and internal connections.
		 * 
		 * @Param nNeurons    number of neurons
		 * @Param nConnect    average internal connections per neurons
		 * @Param rect        2D rectangle
		 * 
		 * @Param distFract   connection length in terms of the diagonal of the rect 0-1.
		 * 
		 */
		super("Grey");

		
		//TODO 
		threshModGrey = new TweakableDouble(tweaks, 0.0, 100.0, 1.0, 0.1,
		"Grey Threshold");

		for (int i = 0; i < nNeurons; i++) {

			float xFact = rand.nextFloat();
			float yFact = rand.nextFloat();
			float dFact = rand.nextFloat();
			
			pramGrey.delayInSecs = (float) (delayMin+(delayMax-delayMin)*dFact);
			Point p = new Point(rect.x + rect.width * xFact, rect.y
					+ rect.height * yFact);
			
			Neuron n = new Neuron(p,  pramGrey);

			neurons.add(n);
			
		}
		// only connect neurons closer than maxDist 
		double maxDist=Math.sqrt(rect.width*rect.width+rect.height*rect.height)*distFract;
		createConnections(maxDist,nConnect,minWeight,maxWeight,brain);
	}
	
	private void createConnections(double maxDist,int avConnect,float minWeight,
			float maxWeight,Brain brain){
		
		int cnt = 0;

		//double maxDist = rect.width * rect.width + rect.height * rect.height;

		int size = neurons.size();

		while (cnt < size * avConnect) {

			for (Neuron n1 : neurons) {
				Neuron n2 = neurons.get((int) (rand.nextDouble() * size));
				if (n1 == n2) {
					continue; // WHY ??
				}

				double dx = n1.pt.x - n2.pt.x;
				double dy = n1.pt.y - n2.pt.y;
				double sep = Math.sqrt( dx * dx + dy * dy);

				if ( sep > maxDist*rand.nextDouble()) {
					continue;
				}

				Neuron in, out;

				in = n1;
				out = n2;
		
				float weight = minWeight+rand.nextFloat()*(maxWeight-minWeight);				
				Connection c = brain.createConnection(in,out, weight);
				cnt++;
			}
		}
	}

	
}
